{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Agent tutorial\n",
    "\n",
    "This tutorial demonstrates AdalFlow agent features on using various tools and dealing with streaming.\n",
    "\n",
    "## Prerequisites\n",
    "1. Install AdalFlow: `pip install adalflow`\n",
    "2. Set OpenAI API key: `export OPENAI_API_KEY=\"your-api-key-here\"`\n",
    "\n",
    "**Note**: This notebook requires an OpenAI API key to function properly."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from IPython.display import clear_output \n",
    "\n",
    "\n",
    "!pip install adalflow pydantic openai\n",
    "\n",
    "# Set OpenAI API key (replace with your actual key)\n",
    "import os\n",
    "os.environ[\"OPENAI_API_KEY\"] = \"your api key\"\n",
    "# Optional: Set Anthropic API key for Anthropic examples\n",
    "# os.environ[\"ANTHROPIC_API_KEY\"] = \"your-anthropic-api-key-here\"\n",
    "clear_output()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Setup and Imports"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "#Import required libraries\n",
    "import os\n",
    "import sys\n",
    "import asyncio\n",
    "from adalflow.components.agent.agent import Agent\n",
    "from adalflow.components.agent.runner import Runner\n",
    "from adalflow.components.model_client import OpenAIClient\n",
    "from adalflow.components.model_client.anthropic_client import AnthropicAPIClient\n",
    "from adalflow.core.func_tool import FunctionTool\n",
    "from adalflow.core.types import (\n",
    "    ToolOutput, \n",
    "    RawResponsesStreamEvent, \n",
    "    RunItemStreamEvent,\n",
    "    ToolCallRunItem,\n",
    "    ToolOutputRunItem,\n",
    "    FinalOutputItem,\n",
    "    ToolCallActivityRunItem\n",
    ")\n",
    "from adalflow.apps.cli_permission_handler import CLIPermissionHandler, AutoApprovalHandler\n",
    "from adalflow.tracing import (\n",
    "    set_tracing_disabled, \n",
    "    enable_mlflow_local, \n",
    "    trace\n",
    ")\n",
    "import adalflow as adal\n",
    "from pathlib import Path\n",
    "import os\n",
    "\n",
    "# ENV_PATH = Path(os.getcwd()).parent.parent / \".env\"\n",
    "# print(ENV_PATH)\n",
    "\n",
    "# # Setup environment\n",
    "# adal.setup_env(ENV_PATH)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'1.1.1'"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "adal.__version__"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Hello World Agent\n",
    "\n",
    "Our agent supports sync, async, sync generator and async generator functions whether it uses tooloutput or not."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Demonstration of all 4 function types supported by AdalFlow agents\n",
    "\n",
    "def calculator(expression: str) -> str:\n",
    "    \"\"\"A synchronous calculator that evaluates mathematical expressions.\"\"\"\n",
    "    try:\n",
    "        result = eval(expression)\n",
    "        return f\"The result of {expression} is {result}\"\n",
    "    except Exception as e:\n",
    "        return f\"Error evaluating expression: {e}\"\n",
    "\n",
    "# 2. Async Function\n",
    "async def web_search(query: str=\"what is the weather in SF today?\") -> str:\n",
    "    \"\"\"web search on query.\"\"\"\n",
    "    # Simulate async operation\n",
    "    await asyncio.sleep(0.5)\n",
    "    return \"San Francisco will be mostly cloudy today with some afternoon sun, reaching about 67 °F (20 °C) and dipping to 57 °F (14 °C) tonight.\"\n",
    "    \n",
    "# streaming tool can include toocallactivity run item and the last one as the final output observable to the llm agent\n",
    "# 3. Sync Generator Function\n",
    "def counter(limit: int):\n",
    "    \"\"\"A counter that counts up to a limit.\"\"\"\n",
    "    final_output = []\n",
    "    for i in range(1, limit + 1):\n",
    "        stream_item =  f\"Count: {i}/{limit}\"\n",
    "        final_output.append(stream_item)\n",
    "        stream_event = ToolCallActivityRunItem(data=stream_item)\n",
    "        yield stream_event\n",
    "\n",
    "    yield final_output\n",
    "\n",
    "# 4. Async Generator Function\n",
    "async def data_streamer(data_type: str):\n",
    "    \"\"\"Streams different types of data.\n",
    "\n",
    "    Args:\n",
    "        data_types can be \"numbers\", \"letters\", \"words\"\n",
    "    \"\"\"\n",
    "    import asyncio\n",
    "    data_items = {\n",
    "        \"numbers\": [1, 2, 3, 4, 5],\n",
    "        \"letters\": [\"a\", \"b\", \"c\", \"d\", \"e\"],\n",
    "        \"words\": [\"hello\", \"world\", \"from\", \"async\", \"generator\"]\n",
    "    }\n",
    "    \n",
    "    items = data_items.get(data_type, [\"unknown\"])\n",
    "    final_output = []\n",
    "    for item in items:\n",
    "        await asyncio.sleep(0.2)  # Simulate async data fetching\n",
    "        stream_item =  f\"Streaming {data_type}: {item}\"\n",
    "        final_output.append(stream_item)\n",
    "        stream_event = ToolCallActivityRunItem(data=stream_item)\n",
    "        yield stream_event\n",
    "\n",
    "    yield final_output\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "# setup the agent \n",
    "\n",
    "agent = Agent(\n",
    "        name=\"StreamingAgent\",\n",
    "        tools=[FunctionTool(calculator), web_search, counter, data_streamer],\n",
    "        model_client=OpenAIClient(),\n",
    "        model_kwargs={\"model\": \"gpt-4o\", \"temperature\": 0.3},\n",
    "        max_steps=5\n",
    "    )\n",
    "\n",
    "runner = Runner(agent=agent)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "query = \"What is 15 * 7 + 23? What is the sf weather, count to 10, and stream different types of data and tell me what is streamed. Must call existing tools.\"\n",
    " # query = \"what is the sf weahter\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Sync call.\n",
    "\n",
    "You can check the stepout where each is of `StepOutput.` Each function comes with `id`, and each step comes with `observation`, even if its an error.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "RunnerResult(step_history=[StepOutput(step=0, planner_prompt=None, action=Function(id='e785bb05-a74a-4870-b3fd-14de2397ac31', thought='First, I will calculate the expression 15 * 7 + 23.', name='calculator', args=[], kwargs={'expression': '15 * 7 + 23'}, _is_answer_final=False, _answer=None), function=Function(id='e785bb05-a74a-4870-b3fd-14de2397ac31', thought='First, I will calculate the expression 15 * 7 + 23.', name='calculator', args=[], kwargs={'expression': '15 * 7 + 23'}, _is_answer_final=False, _answer=None), observation='The result of 15 * 7 + 23 is 128', ctx=None), StepOutput(step=1, planner_prompt=None, action=Function(id='23785514-afa2-4c19-820a-75db7c76e8f3', thought='Next, I will count to 10 using the counter tool.', name='counter', args=[], kwargs={'limit': 10}, _is_answer_final=False, _answer=None), function=Function(id='23785514-afa2-4c19-820a-75db7c76e8f3', thought='Next, I will count to 10 using the counter tool.', name='counter', args=[], kwargs={'limit': 10}, _is_answer_final=False, _answer=None), observation=[['Count: 1/10', 'Count: 2/10', 'Count: 3/10', 'Count: 4/10', 'Count: 5/10', 'Count: 6/10', 'Count: 7/10', 'Count: 8/10', 'Count: 9/10', 'Count: 10/10']], ctx=None)], answer='The result of the expression 15 * 7 + 23 is 128. The counter counted up to 10: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10.', error=None, ctx=None)\n",
      "StepOutput(step=0, planner_prompt=None, action=Function(id='e785bb05-a74a-4870-b3fd-14de2397ac31', thought='First, I will calculate the expression 15 * 7 + 23.', name='calculator', args=[], kwargs={'expression': '15 * 7 + 23'}, _is_answer_final=False, _answer=None), function=Function(id='e785bb05-a74a-4870-b3fd-14de2397ac31', thought='First, I will calculate the expression 15 * 7 + 23.', name='calculator', args=[], kwargs={'expression': '15 * 7 + 23'}, _is_answer_final=False, _answer=None), observation='The result of 15 * 7 + 23 is 128', ctx=None)\n",
      "StepOutput(step=1, planner_prompt=None, action=Function(id='23785514-afa2-4c19-820a-75db7c76e8f3', thought='Next, I will count to 10 using the counter tool.', name='counter', args=[], kwargs={'limit': 10}, _is_answer_final=False, _answer=None), function=Function(id='23785514-afa2-4c19-820a-75db7c76e8f3', thought='Next, I will count to 10 using the counter tool.', name='counter', args=[], kwargs={'limit': 10}, _is_answer_final=False, _answer=None), observation=[['Count: 1/10', 'Count: 2/10', 'Count: 3/10', 'Count: 4/10', 'Count: 5/10', 'Count: 6/10', 'Count: 7/10', 'Count: 8/10', 'Count: 9/10', 'Count: 10/10']], ctx=None)\n",
      "Final Answer:\n",
      "The result of the expression 15 * 7 + 23 is 128. The counter counted up to 10: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10.\n"
     ]
    }
   ],
   "source": [
    "# run call \n",
    "\n",
    "\n",
    "# Note: it should work on both sync and async fun normally, but cant work in the notebook, so we test only sync function \n",
    "\n",
    "\n",
    "agent = Agent(\n",
    "        name=\"StreamingAgent\",\n",
    "        tools=[FunctionTool(calculator), counter],\n",
    "        model_client=OpenAIClient(),\n",
    "        model_kwargs={\"model\": \"gpt-4o\", \"temperature\": 0.3},\n",
    "        max_steps=5\n",
    "    )\n",
    "\n",
    "runner = Runner(agent=agent)\n",
    "\n",
    "def test():\n",
    "    runner_result = runner.call( prompt_kwargs={\"input_str\": query})\n",
    "    print(runner_result)\n",
    "    for step in runner_result.step_history:\n",
    "        print(step)\n",
    "    print(\"Final Answer:\")\n",
    "    print(runner_result.answer)\n",
    "\n",
    "test()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Acall behaves similar to call on the output data structure."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "RunnerResult(step_history=[StepOutput(step=0, planner_prompt=None, action=Function(id='61696c5a-29b2-4295-a8bf-a01a8d1fa9e1', thought='First, calculate the expression 15 * 7 + 23.', name='calculator', args=[], kwargs={'expression': '15 * 7 + 23'}, _is_answer_final=False, _answer=None), function=Function(id='61696c5a-29b2-4295-a8bf-a01a8d1fa9e1', thought='First, calculate the expression 15 * 7 + 23.', name='calculator', args=[], kwargs={'expression': '15 * 7 + 23'}, _is_answer_final=False, _answer=None), observation='The result of 15 * 7 + 23 is 128', ctx=None), StepOutput(step=1, planner_prompt=None, action=Function(id='7d35933c-3554-4e2b-a850-46df87fcaa7a', thought='Next, perform a web search to find the weather in San Francisco.', name='web_search', args=[], kwargs={'query': 'what is the weather in SF today?'}, _is_answer_final=False, _answer=None), function=Function(id='7d35933c-3554-4e2b-a850-46df87fcaa7a', thought='Next, perform a web search to find the weather in San Francisco.', name='web_search', args=[], kwargs={'query': 'what is the weather in SF today?'}, _is_answer_final=False, _answer=None), observation='San Francisco will be mostly cloudy today with some afternoon sun, reaching about 67 °F (20 °C) and dipping to 57 °F (14 °C) tonight.', ctx=None), StepOutput(step=2, planner_prompt=None, action=Function(id='d587b4ba-3698-473d-991c-5b4a2da3e02b', thought='Now, count to 10 using the counter tool.', name='counter', args=[], kwargs={'limit': 10}, _is_answer_final=False, _answer=None), function=Function(id='d587b4ba-3698-473d-991c-5b4a2da3e02b', thought='Now, count to 10 using the counter tool.', name='counter', args=[], kwargs={'limit': 10}, _is_answer_final=False, _answer=None), observation=[['Count: 1/10', 'Count: 2/10', 'Count: 3/10', 'Count: 4/10', 'Count: 5/10', 'Count: 6/10', 'Count: 7/10', 'Count: 8/10', 'Count: 9/10', 'Count: 10/10']], ctx=None), StepOutput(step=3, planner_prompt=None, action=Function(id='916a8aaa-cc31-45bc-b266-621e593358e7', thought='Finally, stream different types of data to complete the query.', name='data_streamer', args=[], kwargs={'data_type': 'numbers'}, _is_answer_final=False, _answer=None), function=Function(id='916a8aaa-cc31-45bc-b266-621e593358e7', thought='Finally, stream different types of data to complete the query.', name='data_streamer', args=[], kwargs={'data_type': 'numbers'}, _is_answer_final=False, _answer=None), observation=[['Streaming numbers: 1', 'Streaming numbers: 2', 'Streaming numbers: 3', 'Streaming numbers: 4', 'Streaming numbers: 5']], ctx=None)], answer='The result of 15 * 7 + 23 is 128. The weather in San Francisco is mostly cloudy with some afternoon sun, reaching about 67 °F (20 °C) and dipping to 57 °F (14 °C) tonight. The count to 10 is complete. The data streamed includes numbers: 1, 2, 3, 4, 5.', error=None, ctx=None)\n",
      "StepOutput(step=0, planner_prompt=None, action=Function(id='61696c5a-29b2-4295-a8bf-a01a8d1fa9e1', thought='First, calculate the expression 15 * 7 + 23.', name='calculator', args=[], kwargs={'expression': '15 * 7 + 23'}, _is_answer_final=False, _answer=None), function=Function(id='61696c5a-29b2-4295-a8bf-a01a8d1fa9e1', thought='First, calculate the expression 15 * 7 + 23.', name='calculator', args=[], kwargs={'expression': '15 * 7 + 23'}, _is_answer_final=False, _answer=None), observation='The result of 15 * 7 + 23 is 128', ctx=None)\n",
      "StepOutput(step=1, planner_prompt=None, action=Function(id='7d35933c-3554-4e2b-a850-46df87fcaa7a', thought='Next, perform a web search to find the weather in San Francisco.', name='web_search', args=[], kwargs={'query': 'what is the weather in SF today?'}, _is_answer_final=False, _answer=None), function=Function(id='7d35933c-3554-4e2b-a850-46df87fcaa7a', thought='Next, perform a web search to find the weather in San Francisco.', name='web_search', args=[], kwargs={'query': 'what is the weather in SF today?'}, _is_answer_final=False, _answer=None), observation='San Francisco will be mostly cloudy today with some afternoon sun, reaching about 67 °F (20 °C) and dipping to 57 °F (14 °C) tonight.', ctx=None)\n",
      "StepOutput(step=2, planner_prompt=None, action=Function(id='d587b4ba-3698-473d-991c-5b4a2da3e02b', thought='Now, count to 10 using the counter tool.', name='counter', args=[], kwargs={'limit': 10}, _is_answer_final=False, _answer=None), function=Function(id='d587b4ba-3698-473d-991c-5b4a2da3e02b', thought='Now, count to 10 using the counter tool.', name='counter', args=[], kwargs={'limit': 10}, _is_answer_final=False, _answer=None), observation=[['Count: 1/10', 'Count: 2/10', 'Count: 3/10', 'Count: 4/10', 'Count: 5/10', 'Count: 6/10', 'Count: 7/10', 'Count: 8/10', 'Count: 9/10', 'Count: 10/10']], ctx=None)\n",
      "StepOutput(step=3, planner_prompt=None, action=Function(id='916a8aaa-cc31-45bc-b266-621e593358e7', thought='Finally, stream different types of data to complete the query.', name='data_streamer', args=[], kwargs={'data_type': 'numbers'}, _is_answer_final=False, _answer=None), function=Function(id='916a8aaa-cc31-45bc-b266-621e593358e7', thought='Finally, stream different types of data to complete the query.', name='data_streamer', args=[], kwargs={'data_type': 'numbers'}, _is_answer_final=False, _answer=None), observation=[['Streaming numbers: 1', 'Streaming numbers: 2', 'Streaming numbers: 3', 'Streaming numbers: 4', 'Streaming numbers: 5']], ctx=None)\n",
      "Final Answer:\n",
      "The result of 15 * 7 + 23 is 128. The weather in San Francisco is mostly cloudy with some afternoon sun, reaching about 67 °F (20 °C) and dipping to 57 °F (14 °C) tonight. The count to 10 is complete. The data streamed includes numbers: 1, 2, 3, 4, 5.\n"
     ]
    }
   ],
   "source": [
    "# run acall\n",
    "\n",
    "agent = Agent(\n",
    "        name=\"StreamingAgent\",\n",
    "        tools=[FunctionTool(calculator), web_search, counter, data_streamer],\n",
    "        model_client=OpenAIClient(),\n",
    "        model_kwargs={\"model\": \"gpt-4o\", \"temperature\": 0.3},\n",
    "        max_steps=5\n",
    "    )\n",
    "\n",
    "runner = Runner(agent=agent)\n",
    "\n",
    "runner_result = await runner.acall( prompt_kwargs={\"input_str\": query})\n",
    "\n",
    "print(runner_result)\n",
    "for step in runner_result.step_history:\n",
    "    print(step)\n",
    "\n",
    "print(\"Final Answer:\")\n",
    "print(runner_result.answer)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Cannot track usage for generator/iterator. Usage tracking should be handled when consuming the stream.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "function name calculator\n",
      "\n",
      "🔧 Calling tool: calculator\n",
      "✅ Tool output: The result of 15 * 7 + 23 is 128\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Cannot track usage for generator/iterator. Usage tracking should be handled when consuming the stream.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "function name web_search\n",
      "\n",
      "🔧 Calling tool: web_search\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Cannot track usage for generator/iterator. Usage tracking should be handled when consuming the stream.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "✅ Tool output: San Francisco will be mostly cloudy today with some afternoon sun, reaching about 67 °F (20 °C) and dipping to 57 °F (14 °C) tonight.\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Cannot track usage for generator/iterator. Usage tracking should be handled when consuming the stream.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "function name counter\n",
      "\n",
      "🔧 Calling tool: counter\n",
      "📝 Activity: Count: 1/10\n",
      "📝 Activity: Count: 2/10\n",
      "📝 Activity: Count: 3/10\n",
      "📝 Activity: Count: 4/10\n",
      "📝 Activity: Count: 5/10\n",
      "📝 Activity: Count: 6/10\n",
      "📝 Activity: Count: 7/10\n",
      "📝 Activity: Count: 8/10\n",
      "📝 Activity: Count: 9/10\n",
      "📝 Activity: Count: 10/10\n",
      "✅ Tool output: ['Count: 1/10', 'Count: 2/10', 'Count: 3/10', 'Count: 4/10', 'Count: 5/10', 'Count: 6/10', 'Count: 7/10', 'Count: 8/10', 'Count: 9/10', 'Count: 10/10']\n",
      "function name data_streamer\n",
      "\n",
      "🔧 Calling tool: data_streamer\n",
      "📝 Activity: Streaming numbers: 1\n",
      "📝 Activity: Streaming numbers: 2\n",
      "📝 Activity: Streaming numbers: 3\n",
      "📝 Activity: Streaming numbers: 4\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Cannot track usage for generator/iterator. Usage tracking should be handled when consuming the stream.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "📝 Activity: Streaming numbers: 5\n",
      "✅ Tool output: ['Streaming numbers: 1', 'Streaming numbers: 2', 'Streaming numbers: 3', 'Streaming numbers: 4', 'Streaming numbers: 5']\n",
      "\n",
      "🎯 Final answer: The result of 15 * 7 + 23 is 128. San Francisco will be mostly cloudy today with some afternoon sun, reaching about 67 °F (20 °C) and dipping to 57 °F (14 °C) tonight. Counted to 10 successfully. Streamed numbers: 1, 2, 3, 4, 5.\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "RunnerStreamingResult(_event_queue=<Queue at 0x30fb4bfd0 maxsize=0 _queue=[RunItemStreamEvent(name='agent.execution_complete', item=FinalOutputItem(id='8c528fda-8f32-4c1c-b086-4562aad4866c', type='final_output', data=RunnerResult(step_history=[StepOutput(step=0, planner_prompt=None, action=Function(id='f5f7afb6-ae22-4fa6-9a1f-0facac1e389f', thought='First, I will calculate the expression 15 * 7 + 23.', name='calculator', args=[], kwargs={'expression': '15 * 7 + 23'}, _is_answer_final=False, _answer=None), function=Function(id='f5f7afb6-ae22-4fa6-9a1f-0facac1e389f', thought='First, I will calculate the expression 15 * 7 + 23.', name='calculator', args=[], kwargs={'expression': '15 * 7 + 23'}, _is_answer_final=False, _answer=None), observation='The result of 15 * 7 + 23 is 128', ctx=None), StepOutput(step=1, planner_prompt=None, action=Function(id='f5a711a1-fba7-4f13-80dd-a44e56f11253', thought='Next, I will search for the weather in San Francisco.', name='web_search', args=[], kwargs={'query': 'what is the weather in SF today?'}, _is_answer_final=False, _answer=None), function=Function(id='f5a711a1-fba7-4f13-80dd-a44e56f11253', thought='Next, I will search for the weather in San Francisco.', name='web_search', args=[], kwargs={'query': 'what is the weather in SF today?'}, _is_answer_final=False, _answer=None), observation='San Francisco will be mostly cloudy today with some afternoon sun, reaching about 67 °F (20 °C) and dipping to 57 °F (14 °C) tonight.', ctx=None), StepOutput(step=2, planner_prompt=None, action=Function(id='75f2daa7-1f25-4e70-afa6-0b9a22244f42', thought='Now, I will count to 10.', name='counter', args=[], kwargs={'limit': 10}, _is_answer_final=False, _answer=None), function=Function(id='75f2daa7-1f25-4e70-afa6-0b9a22244f42', thought='Now, I will count to 10.', name='counter', args=[], kwargs={'limit': 10}, _is_answer_final=False, _answer=None), observation=['Count: 1/10', 'Count: 2/10', 'Count: 3/10', 'Count: 4/10', 'Count: 5/10', 'Count: 6/10', 'Count: 7/10', 'Count: 8/10', 'Count: 9/10', 'Count: 10/10'], ctx=None), StepOutput(step=3, planner_prompt=None, action=Function(id='18234562-4574-4dd1-928d-6b448dda2ba1', thought='Finally, I will stream different types of data and report what is streamed.', name='data_streamer', args=[], kwargs={'data_type': 'numbers'}, _is_answer_final=False, _answer=None), function=Function(id='18234562-4574-4dd1-928d-6b448dda2ba1', thought='Finally, I will stream different types of data and report what is streamed.', name='data_streamer', args=[], kwargs={'data_type': 'numbers'}, _is_answer_final=False, _answer=None), observation=['Streaming numbers: 1', 'Streaming numbers: 2', 'Streaming numbers: 3', 'Streaming numbers: 4', 'Streaming numbers: 5'], ctx=None)], answer='The result of 15 * 7 + 23 is 128. San Francisco will be mostly cloudy today with some afternoon sun, reaching about 67 °F (20 °C) and dipping to 57 °F (14 °C) tonight. Counted to 10 successfully. Streamed numbers: 1, 2, 3, 4, 5.', error=None, ctx=None), error=None, timestamp=datetime.datetime(2025, 8, 15, 17, 7, 59, 830396)), type='run_item_stream_event'), QueueCompleteSentinel()] tasks=2>, _run_task=<Task finished name='Task-3' coro=<Runner.impl_astream() done, defined at /Users/li/github/SylphAI-Inc/adal/backend/AdalFlow/adalflow/adalflow/components/agent/runner.py:1196> result=None>, _exception=None, answer='The result of 15 * 7 + 23 is 128. San Francisco will be mostly cloudy today with some afternoon sun, reaching about 67 °F (20 °C) and dipping to 57 °F (14 °C) tonight. Counted to 10 successfully. Streamed numbers: 1, 2, 3, 4, 5.', step_history=[StepOutput(step=0, planner_prompt=None, action=Function(id='f5f7afb6-ae22-4fa6-9a1f-0facac1e389f', thought='First, I will calculate the expression 15 * 7 + 23.', name='calculator', args=[], kwargs={'expression': '15 * 7 + 23'}, _is_answer_final=False, _answer=None), function=Function(id='f5f7afb6-ae22-4fa6-9a1f-0facac1e389f', thought='First, I will calculate the expression 15 * 7 + 23.', name='calculator', args=[], kwargs={'expression': '15 * 7 + 23'}, _is_answer_final=False, _answer=None), observation='The result of 15 * 7 + 23 is 128', ctx=None), StepOutput(step=1, planner_prompt=None, action=Function(id='f5a711a1-fba7-4f13-80dd-a44e56f11253', thought='Next, I will search for the weather in San Francisco.', name='web_search', args=[], kwargs={'query': 'what is the weather in SF today?'}, _is_answer_final=False, _answer=None), function=Function(id='f5a711a1-fba7-4f13-80dd-a44e56f11253', thought='Next, I will search for the weather in San Francisco.', name='web_search', args=[], kwargs={'query': 'what is the weather in SF today?'}, _is_answer_final=False, _answer=None), observation='San Francisco will be mostly cloudy today with some afternoon sun, reaching about 67 °F (20 °C) and dipping to 57 °F (14 °C) tonight.', ctx=None), StepOutput(step=2, planner_prompt=None, action=Function(id='75f2daa7-1f25-4e70-afa6-0b9a22244f42', thought='Now, I will count to 10.', name='counter', args=[], kwargs={'limit': 10}, _is_answer_final=False, _answer=None), function=Function(id='75f2daa7-1f25-4e70-afa6-0b9a22244f42', thought='Now, I will count to 10.', name='counter', args=[], kwargs={'limit': 10}, _is_answer_final=False, _answer=None), observation=['Count: 1/10', 'Count: 2/10', 'Count: 3/10', 'Count: 4/10', 'Count: 5/10', 'Count: 6/10', 'Count: 7/10', 'Count: 8/10', 'Count: 9/10', 'Count: 10/10'], ctx=None), StepOutput(step=3, planner_prompt=None, action=Function(id='18234562-4574-4dd1-928d-6b448dda2ba1', thought='Finally, I will stream different types of data and report what is streamed.', name='data_streamer', args=[], kwargs={'data_type': 'numbers'}, _is_answer_final=False, _answer=None), function=Function(id='18234562-4574-4dd1-928d-6b448dda2ba1', thought='Finally, I will stream different types of data and report what is streamed.', name='data_streamer', args=[], kwargs={'data_type': 'numbers'}, _is_answer_final=False, _answer=None), observation=['Streaming numbers: 1', 'Streaming numbers: 2', 'Streaming numbers: 3', 'Streaming numbers: 4', 'Streaming numbers: 5'], ctx=None)], _is_complete=True)"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# run async streaming with streaming events\n",
    "\n",
    "async def run_astrem():\n",
    "    streaming_result = runner.astream(\n",
    "            prompt_kwargs={\"input_str\": query},\n",
    "            model_kwargs={\"stream\": True}\n",
    "    )\n",
    "\n",
    "    # Process streaming events\n",
    "    async for event in streaming_result.stream_events():\n",
    "        if isinstance(event, RunItemStreamEvent):\n",
    "            if isinstance(event.item, ToolCallRunItem):\n",
    "                print(f\"\\n🔧 Calling tool: {event.item.data.name}\")\n",
    "                \n",
    "            elif isinstance(event.item, ToolOutputRunItem):\n",
    "                print(f\"✅ Tool output: {event.item.data.output}\")\n",
    "                \n",
    "            elif isinstance(event.item, ToolCallActivityRunItem):\n",
    "                # This captures generator yields\n",
    "                print(f\"📝 Activity: {event.item.data}\")\n",
    "                \n",
    "            elif isinstance(event.item, FinalOutputItem):\n",
    "                print(f\"\\n🎯 Final answer: {event.item.data.answer}\")\n",
    "\n",
    "    return streaming_result\n",
    "\n",
    "asyncio.run(run_astrem())\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Streaming Raw Responses\n",
    "\n",
    "This is the same with `astream` above with `delta` which streams the intermediate function call."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Cannot track usage for generator/iterator. Usage tracking should be handled when consuming the stream.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "=== Streaming Raw Responses Example ===\n",
      "Raw streaming output:\n",
      "{\n",
      "    \"thought\": \"First, I will calculate the expression 15 * 7 + 23.\",\n",
      "    \"name\": \"calculator\",\n",
      "    \"kwargs\": {\n",
      "        \"expression\": \"15 * 7 + 23\"\n",
      "    },\n",
      "    \"_is_answer_final\": false\n",
      "}function name calculator\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Cannot track usage for generator/iterator. Usage tracking should be handled when consuming the stream.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "```json\n",
      "{\n",
      "    \"thought\": \"Next, I will check the weather in San Francisco.\",\n",
      "    \"name\": \"web_search\",\n",
      "    \"kwargs\": {\n",
      "        \"query\": \"what is the weather in SF today?\"\n",
      "    },\n",
      "    \"_is_answer_final\": false\n",
      "}\n",
      "```function name web_search\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Cannot track usage for generator/iterator. Usage tracking should be handled when consuming the stream.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{\n",
      "    \"thought\": \"Now, I will count to 10.\",\n",
      "    \"name\": \"counter\",\n",
      "    \"kwargs\": {\n",
      "        \"limit\": 10\n",
      "    },\n",
      "    \"_is_answer_final\": false\n",
      "}function name counter\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Cannot track usage for generator/iterator. Usage tracking should be handled when consuming the stream.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{\n",
      "    \"thought\": \"Finally, I will stream different types of data and report what is streamed.\",\n",
      "    \"name\": \"data_streamer\",\n",
      "    \"kwargs\": {\n",
      "        \"data_type\": \"numbers\"\n",
      "    },\n",
      "    \"_is_answer_final\": False\n",
      "}function name data_streamer\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Cannot track usage for generator/iterator. Usage tracking should be handled when consuming the stream.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{\n",
      "    \"thought\": \"I have completed all the tasks: calculated the expression, checked the weather, counted to 10, and streamed numbers.\",\n",
      "    \"_is_answer_final\": true,\n",
      "    \"_answer\": \"The result of 15 * 7 + 23 is 128. The weather in San Francisco is mostly cloudy with some afternoon sun, reaching about 67 °F (20 °C) and dipping to 57 °F (14 °C) tonight. Counted to 10 successfully. Streamed numbers: 1, 2, 3, 4, 5.\"\n",
      "}\n",
      "\n",
      "\n",
      "Final Result:\n",
      "The result of 15 * 7 + 23 is 128. The weather in San Francisco is mostly cloudy with some afternoon sun, reaching about 67 °F (20 °C) and dipping to 57 °F (14 °C) tonight. Counted to 10 successfully. Streamed numbers: 1, 2, 3, 4, 5.\n",
      "\n",
      "Step History:\n",
      "StepOutput(step=0, planner_prompt=None, action=Function(id='34608cd1-724f-4b5b-a372-0f9f4868de3c', thought='First, I will calculate the expression 15 * 7 + 23.', name='calculator', args=[], kwargs={'expression': '15 * 7 + 23'}, _is_answer_final=False, _answer=None), function=Function(id='34608cd1-724f-4b5b-a372-0f9f4868de3c', thought='First, I will calculate the expression 15 * 7 + 23.', name='calculator', args=[], kwargs={'expression': '15 * 7 + 23'}, _is_answer_final=False, _answer=None), observation='The result of 15 * 7 + 23 is 128', ctx=None)\n",
      "StepOutput(step=1, planner_prompt=None, action=Function(id='3d37370f-5d55-4bab-8749-668c6d0794ad', thought='Next, I will check the weather in San Francisco.', name='web_search', args=[], kwargs={'query': 'what is the weather in SF today?'}, _is_answer_final=False, _answer=None), function=Function(id='3d37370f-5d55-4bab-8749-668c6d0794ad', thought='Next, I will check the weather in San Francisco.', name='web_search', args=[], kwargs={'query': 'what is the weather in SF today?'}, _is_answer_final=False, _answer=None), observation='San Francisco will be mostly cloudy today with some afternoon sun, reaching about 67 °F (20 °C) and dipping to 57 °F (14 °C) tonight.', ctx=None)\n",
      "StepOutput(step=2, planner_prompt=None, action=Function(id='5047f06d-f5fa-4d52-a4b6-47cc8421ac1a', thought='Now, I will count to 10.', name='counter', args=[], kwargs={'limit': 10}, _is_answer_final=False, _answer=None), function=Function(id='5047f06d-f5fa-4d52-a4b6-47cc8421ac1a', thought='Now, I will count to 10.', name='counter', args=[], kwargs={'limit': 10}, _is_answer_final=False, _answer=None), observation=['Count: 1/10', 'Count: 2/10', 'Count: 3/10', 'Count: 4/10', 'Count: 5/10', 'Count: 6/10', 'Count: 7/10', 'Count: 8/10', 'Count: 9/10', 'Count: 10/10'], ctx=None)\n",
      "StepOutput(step=3, planner_prompt=None, action=Function(id='8c6653d6-6d8c-444e-883b-a050a2a01a42', thought='Finally, I will stream different types of data and report what is streamed.', name='data_streamer', args=[], kwargs={'data_type': 'numbers'}, _is_answer_final=False, _answer=None), function=Function(id='8c6653d6-6d8c-444e-883b-a050a2a01a42', thought='Finally, I will stream different types of data and report what is streamed.', name='data_streamer', args=[], kwargs={'data_type': 'numbers'}, _is_answer_final=False, _answer=None), observation=['Streaming numbers: 1', 'Streaming numbers: 2', 'Streaming numbers: 3', 'Streaming numbers: 4', 'Streaming numbers: 5'], ctx=None)\n",
      "\n",
      "Final Runner Result:\n",
      "RunItemStreamEvent(name='agent.execution_complete', item=FinalOutputItem(id='c72e109d-851c-4c4c-a6fe-d8b1318013fc', type='final_output', data=RunnerResult(step_history=[StepOutput(step=0, planner_prompt=None, action=Function(id='34608cd1-724f-4b5b-a372-0f9f4868de3c', thought='First, I will calculate the expression 15 * 7 + 23.', name='calculator', args=[], kwargs={'expression': '15 * 7 + 23'}, _is_answer_final=False, _answer=None), function=Function(id='34608cd1-724f-4b5b-a372-0f9f4868de3c', thought='First, I will calculate the expression 15 * 7 + 23.', name='calculator', args=[], kwargs={'expression': '15 * 7 + 23'}, _is_answer_final=False, _answer=None), observation='The result of 15 * 7 + 23 is 128', ctx=None), StepOutput(step=1, planner_prompt=None, action=Function(id='3d37370f-5d55-4bab-8749-668c6d0794ad', thought='Next, I will check the weather in San Francisco.', name='web_search', args=[], kwargs={'query': 'what is the weather in SF today?'}, _is_answer_final=False, _answer=None), function=Function(id='3d37370f-5d55-4bab-8749-668c6d0794ad', thought='Next, I will check the weather in San Francisco.', name='web_search', args=[], kwargs={'query': 'what is the weather in SF today?'}, _is_answer_final=False, _answer=None), observation='San Francisco will be mostly cloudy today with some afternoon sun, reaching about 67 °F (20 °C) and dipping to 57 °F (14 °C) tonight.', ctx=None), StepOutput(step=2, planner_prompt=None, action=Function(id='5047f06d-f5fa-4d52-a4b6-47cc8421ac1a', thought='Now, I will count to 10.', name='counter', args=[], kwargs={'limit': 10}, _is_answer_final=False, _answer=None), function=Function(id='5047f06d-f5fa-4d52-a4b6-47cc8421ac1a', thought='Now, I will count to 10.', name='counter', args=[], kwargs={'limit': 10}, _is_answer_final=False, _answer=None), observation=['Count: 1/10', 'Count: 2/10', 'Count: 3/10', 'Count: 4/10', 'Count: 5/10', 'Count: 6/10', 'Count: 7/10', 'Count: 8/10', 'Count: 9/10', 'Count: 10/10'], ctx=None), StepOutput(step=3, planner_prompt=None, action=Function(id='8c6653d6-6d8c-444e-883b-a050a2a01a42', thought='Finally, I will stream different types of data and report what is streamed.', name='data_streamer', args=[], kwargs={'data_type': 'numbers'}, _is_answer_final=False, _answer=None), function=Function(id='8c6653d6-6d8c-444e-883b-a050a2a01a42', thought='Finally, I will stream different types of data and report what is streamed.', name='data_streamer', args=[], kwargs={'data_type': 'numbers'}, _is_answer_final=False, _answer=None), observation=['Streaming numbers: 1', 'Streaming numbers: 2', 'Streaming numbers: 3', 'Streaming numbers: 4', 'Streaming numbers: 5'], ctx=None)], answer='The result of 15 * 7 + 23 is 128. The weather in San Francisco is mostly cloudy with some afternoon sun, reaching about 67 °F (20 °C) and dipping to 57 °F (14 °C) tonight. Counted to 10 successfully. Streamed numbers: 1, 2, 3, 4, 5.', error=None, ctx=None), error=None, timestamp=datetime.datetime(2025, 8, 15, 17, 23, 17, 756837)), type='run_item_stream_event')\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "RunnerStreamingResult(_event_queue=<Queue at 0x31439add0 maxsize=0 _queue=[RunItemStreamEvent(name='agent.execution_complete', item=FinalOutputItem(id='c72e109d-851c-4c4c-a6fe-d8b1318013fc', type='final_output', data=RunnerResult(step_history=[StepOutput(step=0, planner_prompt=None, action=Function(id='34608cd1-724f-4b5b-a372-0f9f4868de3c', thought='First, I will calculate the expression 15 * 7 + 23.', name='calculator', args=[], kwargs={'expression': '15 * 7 + 23'}, _is_answer_final=False, _answer=None), function=Function(id='34608cd1-724f-4b5b-a372-0f9f4868de3c', thought='First, I will calculate the expression 15 * 7 + 23.', name='calculator', args=[], kwargs={'expression': '15 * 7 + 23'}, _is_answer_final=False, _answer=None), observation='The result of 15 * 7 + 23 is 128', ctx=None), StepOutput(step=1, planner_prompt=None, action=Function(id='3d37370f-5d55-4bab-8749-668c6d0794ad', thought='Next, I will check the weather in San Francisco.', name='web_search', args=[], kwargs={'query': 'what is the weather in SF today?'}, _is_answer_final=False, _answer=None), function=Function(id='3d37370f-5d55-4bab-8749-668c6d0794ad', thought='Next, I will check the weather in San Francisco.', name='web_search', args=[], kwargs={'query': 'what is the weather in SF today?'}, _is_answer_final=False, _answer=None), observation='San Francisco will be mostly cloudy today with some afternoon sun, reaching about 67 °F (20 °C) and dipping to 57 °F (14 °C) tonight.', ctx=None), StepOutput(step=2, planner_prompt=None, action=Function(id='5047f06d-f5fa-4d52-a4b6-47cc8421ac1a', thought='Now, I will count to 10.', name='counter', args=[], kwargs={'limit': 10}, _is_answer_final=False, _answer=None), function=Function(id='5047f06d-f5fa-4d52-a4b6-47cc8421ac1a', thought='Now, I will count to 10.', name='counter', args=[], kwargs={'limit': 10}, _is_answer_final=False, _answer=None), observation=['Count: 1/10', 'Count: 2/10', 'Count: 3/10', 'Count: 4/10', 'Count: 5/10', 'Count: 6/10', 'Count: 7/10', 'Count: 8/10', 'Count: 9/10', 'Count: 10/10'], ctx=None), StepOutput(step=3, planner_prompt=None, action=Function(id='8c6653d6-6d8c-444e-883b-a050a2a01a42', thought='Finally, I will stream different types of data and report what is streamed.', name='data_streamer', args=[], kwargs={'data_type': 'numbers'}, _is_answer_final=False, _answer=None), function=Function(id='8c6653d6-6d8c-444e-883b-a050a2a01a42', thought='Finally, I will stream different types of data and report what is streamed.', name='data_streamer', args=[], kwargs={'data_type': 'numbers'}, _is_answer_final=False, _answer=None), observation=['Streaming numbers: 1', 'Streaming numbers: 2', 'Streaming numbers: 3', 'Streaming numbers: 4', 'Streaming numbers: 5'], ctx=None)], answer='The result of 15 * 7 + 23 is 128. The weather in San Francisco is mostly cloudy with some afternoon sun, reaching about 67 °F (20 °C) and dipping to 57 °F (14 °C) tonight. Counted to 10 successfully. Streamed numbers: 1, 2, 3, 4, 5.', error=None, ctx=None), error=None, timestamp=datetime.datetime(2025, 8, 15, 17, 23, 17, 756837)), type='run_item_stream_event'), QueueCompleteSentinel()] tasks=2>, _run_task=<Task finished name='Task-37' coro=<Runner.impl_astream() done, defined at /Users/li/github/SylphAI-Inc/adal/backend/AdalFlow/adalflow/adalflow/components/agent/runner.py:1196> result=None>, _exception=None, answer='The result of 15 * 7 + 23 is 128. The weather in San Francisco is mostly cloudy with some afternoon sun, reaching about 67 °F (20 °C) and dipping to 57 °F (14 °C) tonight. Counted to 10 successfully. Streamed numbers: 1, 2, 3, 4, 5.', step_history=[StepOutput(step=0, planner_prompt=None, action=Function(id='34608cd1-724f-4b5b-a372-0f9f4868de3c', thought='First, I will calculate the expression 15 * 7 + 23.', name='calculator', args=[], kwargs={'expression': '15 * 7 + 23'}, _is_answer_final=False, _answer=None), function=Function(id='34608cd1-724f-4b5b-a372-0f9f4868de3c', thought='First, I will calculate the expression 15 * 7 + 23.', name='calculator', args=[], kwargs={'expression': '15 * 7 + 23'}, _is_answer_final=False, _answer=None), observation='The result of 15 * 7 + 23 is 128', ctx=None), StepOutput(step=1, planner_prompt=None, action=Function(id='3d37370f-5d55-4bab-8749-668c6d0794ad', thought='Next, I will check the weather in San Francisco.', name='web_search', args=[], kwargs={'query': 'what is the weather in SF today?'}, _is_answer_final=False, _answer=None), function=Function(id='3d37370f-5d55-4bab-8749-668c6d0794ad', thought='Next, I will check the weather in San Francisco.', name='web_search', args=[], kwargs={'query': 'what is the weather in SF today?'}, _is_answer_final=False, _answer=None), observation='San Francisco will be mostly cloudy today with some afternoon sun, reaching about 67 °F (20 °C) and dipping to 57 °F (14 °C) tonight.', ctx=None), StepOutput(step=2, planner_prompt=None, action=Function(id='5047f06d-f5fa-4d52-a4b6-47cc8421ac1a', thought='Now, I will count to 10.', name='counter', args=[], kwargs={'limit': 10}, _is_answer_final=False, _answer=None), function=Function(id='5047f06d-f5fa-4d52-a4b6-47cc8421ac1a', thought='Now, I will count to 10.', name='counter', args=[], kwargs={'limit': 10}, _is_answer_final=False, _answer=None), observation=['Count: 1/10', 'Count: 2/10', 'Count: 3/10', 'Count: 4/10', 'Count: 5/10', 'Count: 6/10', 'Count: 7/10', 'Count: 8/10', 'Count: 9/10', 'Count: 10/10'], ctx=None), StepOutput(step=3, planner_prompt=None, action=Function(id='8c6653d6-6d8c-444e-883b-a050a2a01a42', thought='Finally, I will stream different types of data and report what is streamed.', name='data_streamer', args=[], kwargs={'data_type': 'numbers'}, _is_answer_final=False, _answer=None), function=Function(id='8c6653d6-6d8c-444e-883b-a050a2a01a42', thought='Finally, I will stream different types of data and report what is streamed.', name='data_streamer', args=[], kwargs={'data_type': 'numbers'}, _is_answer_final=False, _answer=None), observation=['Streaming numbers: 1', 'Streaming numbers: 2', 'Streaming numbers: 3', 'Streaming numbers: 4', 'Streaming numbers: 5'], ctx=None)], _is_complete=True)"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "async def streaming_raw_responses_example():\n",
    "    \"\"\"Demonstrates handling raw response stream events.\"\"\"\n",
    "    print(\"\\n=== Streaming Raw Responses Example ===\")\n",
    "    streaming_result = runner.astream(\n",
    "        prompt_kwargs={\"input_str\": query},\n",
    "        model_kwargs={\"stream\": True}\n",
    "    )\n",
    "\n",
    "    print(\"Raw streaming output:\")\n",
    "    last_event = None\n",
    "    async for event in streaming_result.stream_events():\n",
    "        if isinstance(event, RawResponsesStreamEvent):\n",
    "            # print(f\"\\n🔄 Raw response event: {event.data}\")\n",
    "            # Process raw model output\n",
    "            # check delta field \n",
    "            if hasattr(event.data, 'delta') and event.data.delta:\n",
    "                delta = event.data.delta\n",
    "                print(delta, end='', flush=True)\n",
    "        last_event = event\n",
    "\n",
    "    print(\"\\n\")  # Add newline after streaming\n",
    "\n",
    "    # get the final runner result \n",
    "    print(\"\\nFinal Result:\")\n",
    "    if hasattr(streaming_result, 'answer'):\n",
    "        print(streaming_result.answer)\n",
    "    else:\n",
    "        print(\"No final answer available.\")\n",
    "\n",
    "\n",
    "    # step through the step history\n",
    "    print(\"\\nStep History:\")\n",
    "    for step in streaming_result.step_history:\n",
    "        print(step)\n",
    "    \n",
    "\n",
    "    # get the final runner result\n",
    "    print(\"\\nFinal Runner Result:\")\n",
    "    print(last_event)\n",
    "    return streaming_result\n",
    "\n",
    "# Run the async example\n",
    "await streaming_raw_responses_example()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Streaming with Anthropic\n",
    "\n",
    "The output works the same as OpenAI as we have standardized the output structure."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "=== Streaming Anthropic Example ===\n",
      "{\n",
      "    \"thought\": \"I'll first use the calculator to compute 42 * 3, and then I'll explore the potential significance of this number.\",\n",
      "    \"name\": \"calculator\",\n",
      "    \"kwargs\": {\n",
      "        \"expression\": \"42 * 3\"\n",
      "    },\n",
      "    \"_is_answer_final\": false\n",
      "}function name calculator\n",
      "{\n",
      "    \"thought\": \"I'll explore the significance of the number 126, drawing from cultural and mathematical references.\",\n",
      "    \"name\": \"web_search\",\n",
      "    \"kwargs\": {\"query\": \"Significance of the number 126 in culture, math, or science\"},\n",
      "    \"_is_answer_final\": false\n",
      "}function name web_search\n",
      "{\n",
      "    \"thought\": \"I noticed the previous web search didn't provide meaningful information about 126. I'll do a more targeted search about the number and its potential significance.\",\n",
      "    \"name\": \"web_search\",\n",
      "    \"kwargs\": {\"query\": \"Interesting mathematical or cultural significance of the number 126\"},\n",
      "    \"_is_answer_final\": false\n",
      "}function name web_search\n",
      "{\n",
      "    \"thought\": \"I'll first recall the calculation result and then provide a comprehensive explanation about the significance of 126, drawing from the previous steps and my knowledge.\",\n",
      "    \"_is_answer_final\": true,\n",
      "    \"_answer\": \"The calculation 42 * 3 = 126 has some interesting mathematical properties:\\n\\n1. Numerical Significance:\\n- 126 is an even number\\n- It's a composite number with factors including 1, 2, 3, 6, 7, 9, 14, 18, 21, 42, 63, and 126\\n- In the context of 'The Hitchhiker's Guide to Galaxy', 42 is famously known as the 'Answer to the Ultimate Question of Life, the Universe, and Everything', so 126 could be seen as a playful multiplication of this mystical number\\n\\n2. Mathematical Curiosity:\\n- 126 is the sum of the first 7 triangular numbers (1 + 3 + 6 + 10 + 15 + 21 + 28)\\n- In number theory, it has some unique properties that make it an interesting number beyond a simple product\\n\\nWhile not having a singular profound significance, 126 represents an intriguing mathematical result that emerges from multiplying 42 by 3, blending numerical curiosity with a touch of playful mathematical exploration.\"\n",
      "}\n",
      "\n",
      "\n",
      "Final Result:\n",
      "The calculation 42 * 3 = 126 has some interesting mathematical properties:\n",
      "\n",
      "1. Numerical Significance:\n",
      "- 126 is an even number\n",
      "- It's a composite number with factors including 1, 2, 3, 6, 7, 9, 14, 18, 21, 42, 63, and 126\n",
      "- In the context of 'The Hitchhiker's Guide to Galaxy', 42 is famously known as the 'Answer to the Ultimate Question of Life, the Universe, and Everything', so 126 could be seen as a playful multiplication of this mystical number\n",
      "\n",
      "2. Mathematical Curiosity:\n",
      "- 126 is the sum of the first 7 triangular numbers (1 + 3 + 6 + 10 + 15 + 21 + 28)\n",
      "- In number theory, it has some unique properties that make it an interesting number beyond a simple product\n",
      "\n",
      "While not having a singular profound significance, 126 represents an intriguing mathematical result that emerges from multiplying 42 by 3, blending numerical curiosity with a touch of playful mathematical exploration.\n",
      "\n",
      "Step History:\n",
      "StepOutput(step=0, planner_prompt=None, action=Function(id='b5a6fb52-e40a-4125-85d8-462c50bef08d', thought=\"I'll first use the calculator to compute 42 * 3, and then I'll explore the potential significance of this number.\", name='calculator', args=[], kwargs={'expression': '42 * 3'}, _is_answer_final=False, _answer=None), function=Function(id='b5a6fb52-e40a-4125-85d8-462c50bef08d', thought=\"I'll first use the calculator to compute 42 * 3, and then I'll explore the potential significance of this number.\", name='calculator', args=[], kwargs={'expression': '42 * 3'}, _is_answer_final=False, _answer=None), observation='The result of 42 * 3 is 126', ctx=None)\n",
      "StepOutput(step=1, planner_prompt=None, action=Function(id='467f1b7e-5eda-4990-b454-1d08130ceaa2', thought=\"I'll explore the significance of the number 126, drawing from cultural and mathematical references.\", name='web_search', args=[], kwargs={'query': 'Significance of the number 126 in culture, math, or science'}, _is_answer_final=False, _answer=None), function=Function(id='467f1b7e-5eda-4990-b454-1d08130ceaa2', thought=\"I'll explore the significance of the number 126, drawing from cultural and mathematical references.\", name='web_search', args=[], kwargs={'query': 'Significance of the number 126 in culture, math, or science'}, _is_answer_final=False, _answer=None), observation='San Francisco will be mostly cloudy today with some afternoon sun, reaching about 67 °F (20 °C) and dipping to 57 °F (14 °C) tonight.', ctx=None)\n",
      "StepOutput(step=2, planner_prompt=None, action=Function(id='05cb9bad-f563-46d8-809a-91d34b0993ac', thought=\"I noticed the previous web search didn't provide meaningful information about 126. I'll do a more targeted search about the number and its potential significance.\", name='web_search', args=[], kwargs={'query': 'Interesting mathematical or cultural significance of the number 126'}, _is_answer_final=False, _answer=None), function=Function(id='05cb9bad-f563-46d8-809a-91d34b0993ac', thought=\"I noticed the previous web search didn't provide meaningful information about 126. I'll do a more targeted search about the number and its potential significance.\", name='web_search', args=[], kwargs={'query': 'Interesting mathematical or cultural significance of the number 126'}, _is_answer_final=False, _answer=None), observation='San Francisco will be mostly cloudy today with some afternoon sun, reaching about 67 °F (20 °C) and dipping to 57 °F (14 °C) tonight.', ctx=None)\n",
      "\n",
      "Final Runner Result:\n",
      "RunItemStreamEvent(name='agent.execution_complete', item=FinalOutputItem(id='97a37a56-218d-4ccd-9048-20e88a6e1a10', type='final_output', data=RunnerResult(step_history=[StepOutput(step=0, planner_prompt=None, action=Function(id='b5a6fb52-e40a-4125-85d8-462c50bef08d', thought=\"I'll first use the calculator to compute 42 * 3, and then I'll explore the potential significance of this number.\", name='calculator', args=[], kwargs={'expression': '42 * 3'}, _is_answer_final=False, _answer=None), function=Function(id='b5a6fb52-e40a-4125-85d8-462c50bef08d', thought=\"I'll first use the calculator to compute 42 * 3, and then I'll explore the potential significance of this number.\", name='calculator', args=[], kwargs={'expression': '42 * 3'}, _is_answer_final=False, _answer=None), observation='The result of 42 * 3 is 126', ctx=None), StepOutput(step=1, planner_prompt=None, action=Function(id='467f1b7e-5eda-4990-b454-1d08130ceaa2', thought=\"I'll explore the significance of the number 126, drawing from cultural and mathematical references.\", name='web_search', args=[], kwargs={'query': 'Significance of the number 126 in culture, math, or science'}, _is_answer_final=False, _answer=None), function=Function(id='467f1b7e-5eda-4990-b454-1d08130ceaa2', thought=\"I'll explore the significance of the number 126, drawing from cultural and mathematical references.\", name='web_search', args=[], kwargs={'query': 'Significance of the number 126 in culture, math, or science'}, _is_answer_final=False, _answer=None), observation='San Francisco will be mostly cloudy today with some afternoon sun, reaching about 67 °F (20 °C) and dipping to 57 °F (14 °C) tonight.', ctx=None), StepOutput(step=2, planner_prompt=None, action=Function(id='05cb9bad-f563-46d8-809a-91d34b0993ac', thought=\"I noticed the previous web search didn't provide meaningful information about 126. I'll do a more targeted search about the number and its potential significance.\", name='web_search', args=[], kwargs={'query': 'Interesting mathematical or cultural significance of the number 126'}, _is_answer_final=False, _answer=None), function=Function(id='05cb9bad-f563-46d8-809a-91d34b0993ac', thought=\"I noticed the previous web search didn't provide meaningful information about 126. I'll do a more targeted search about the number and its potential significance.\", name='web_search', args=[], kwargs={'query': 'Interesting mathematical or cultural significance of the number 126'}, _is_answer_final=False, _answer=None), observation='San Francisco will be mostly cloudy today with some afternoon sun, reaching about 67 °F (20 °C) and dipping to 57 °F (14 °C) tonight.', ctx=None)], answer=\"The calculation 42 * 3 = 126 has some interesting mathematical properties:\\n\\n1. Numerical Significance:\\n- 126 is an even number\\n- It's a composite number with factors including 1, 2, 3, 6, 7, 9, 14, 18, 21, 42, 63, and 126\\n- In the context of 'The Hitchhiker's Guide to Galaxy', 42 is famously known as the 'Answer to the Ultimate Question of Life, the Universe, and Everything', so 126 could be seen as a playful multiplication of this mystical number\\n\\n2. Mathematical Curiosity:\\n- 126 is the sum of the first 7 triangular numbers (1 + 3 + 6 + 10 + 15 + 21 + 28)\\n- In number theory, it has some unique properties that make it an interesting number beyond a simple product\\n\\nWhile not having a singular profound significance, 126 represents an intriguing mathematical result that emerges from multiplying 42 by 3, blending numerical curiosity with a touch of playful mathematical exploration.\", error=None, ctx=None), error=None, timestamp=datetime.datetime(2025, 8, 15, 17, 25, 55, 97787)), type='run_item_stream_event')\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "RunnerStreamingResult(_event_queue=<Queue at 0x3129826d0 maxsize=0 _queue=[RunItemStreamEvent(name='agent.execution_complete', item=FinalOutputItem(id='97a37a56-218d-4ccd-9048-20e88a6e1a10', type='final_output', data=RunnerResult(step_history=[StepOutput(step=0, planner_prompt=None, action=Function(id='b5a6fb52-e40a-4125-85d8-462c50bef08d', thought=\"I'll first use the calculator to compute 42 * 3, and then I'll explore the potential significance of this number.\", name='calculator', args=[], kwargs={'expression': '42 * 3'}, _is_answer_final=False, _answer=None), function=Function(id='b5a6fb52-e40a-4125-85d8-462c50bef08d', thought=\"I'll first use the calculator to compute 42 * 3, and then I'll explore the potential significance of this number.\", name='calculator', args=[], kwargs={'expression': '42 * 3'}, _is_answer_final=False, _answer=None), observation='The result of 42 * 3 is 126', ctx=None), StepOutput(step=1, planner_prompt=None, action=Function(id='467f1b7e-5eda-4990-b454-1d08130ceaa2', thought=\"I'll explore the significance of the number 126, drawing from cultural and mathematical references.\", name='web_search', args=[], kwargs={'query': 'Significance of the number 126 in culture, math, or science'}, _is_answer_final=False, _answer=None), function=Function(id='467f1b7e-5eda-4990-b454-1d08130ceaa2', thought=\"I'll explore the significance of the number 126, drawing from cultural and mathematical references.\", name='web_search', args=[], kwargs={'query': 'Significance of the number 126 in culture, math, or science'}, _is_answer_final=False, _answer=None), observation='San Francisco will be mostly cloudy today with some afternoon sun, reaching about 67 °F (20 °C) and dipping to 57 °F (14 °C) tonight.', ctx=None), StepOutput(step=2, planner_prompt=None, action=Function(id='05cb9bad-f563-46d8-809a-91d34b0993ac', thought=\"I noticed the previous web search didn't provide meaningful information about 126. I'll do a more targeted search about the number and its potential significance.\", name='web_search', args=[], kwargs={'query': 'Interesting mathematical or cultural significance of the number 126'}, _is_answer_final=False, _answer=None), function=Function(id='05cb9bad-f563-46d8-809a-91d34b0993ac', thought=\"I noticed the previous web search didn't provide meaningful information about 126. I'll do a more targeted search about the number and its potential significance.\", name='web_search', args=[], kwargs={'query': 'Interesting mathematical or cultural significance of the number 126'}, _is_answer_final=False, _answer=None), observation='San Francisco will be mostly cloudy today with some afternoon sun, reaching about 67 °F (20 °C) and dipping to 57 °F (14 °C) tonight.', ctx=None)], answer=\"The calculation 42 * 3 = 126 has some interesting mathematical properties:\\n\\n1. Numerical Significance:\\n- 126 is an even number\\n- It's a composite number with factors including 1, 2, 3, 6, 7, 9, 14, 18, 21, 42, 63, and 126\\n- In the context of 'The Hitchhiker's Guide to Galaxy', 42 is famously known as the 'Answer to the Ultimate Question of Life, the Universe, and Everything', so 126 could be seen as a playful multiplication of this mystical number\\n\\n2. Mathematical Curiosity:\\n- 126 is the sum of the first 7 triangular numbers (1 + 3 + 6 + 10 + 15 + 21 + 28)\\n- In number theory, it has some unique properties that make it an interesting number beyond a simple product\\n\\nWhile not having a singular profound significance, 126 represents an intriguing mathematical result that emerges from multiplying 42 by 3, blending numerical curiosity with a touch of playful mathematical exploration.\", error=None, ctx=None), error=None, timestamp=datetime.datetime(2025, 8, 15, 17, 25, 55, 97787)), type='run_item_stream_event'), QueueCompleteSentinel()] tasks=2>, _run_task=<Task finished name='Task-46' coro=<Runner.impl_astream() done, defined at /Users/li/github/SylphAI-Inc/adal/backend/AdalFlow/adalflow/adalflow/components/agent/runner.py:1196> result=None>, _exception=None, answer=\"The calculation 42 * 3 = 126 has some interesting mathematical properties:\\n\\n1. Numerical Significance:\\n- 126 is an even number\\n- It's a composite number with factors including 1, 2, 3, 6, 7, 9, 14, 18, 21, 42, 63, and 126\\n- In the context of 'The Hitchhiker's Guide to Galaxy', 42 is famously known as the 'Answer to the Ultimate Question of Life, the Universe, and Everything', so 126 could be seen as a playful multiplication of this mystical number\\n\\n2. Mathematical Curiosity:\\n- 126 is the sum of the first 7 triangular numbers (1 + 3 + 6 + 10 + 15 + 21 + 28)\\n- In number theory, it has some unique properties that make it an interesting number beyond a simple product\\n\\nWhile not having a singular profound significance, 126 represents an intriguing mathematical result that emerges from multiplying 42 by 3, blending numerical curiosity with a touch of playful mathematical exploration.\", step_history=[StepOutput(step=0, planner_prompt=None, action=Function(id='b5a6fb52-e40a-4125-85d8-462c50bef08d', thought=\"I'll first use the calculator to compute 42 * 3, and then I'll explore the potential significance of this number.\", name='calculator', args=[], kwargs={'expression': '42 * 3'}, _is_answer_final=False, _answer=None), function=Function(id='b5a6fb52-e40a-4125-85d8-462c50bef08d', thought=\"I'll first use the calculator to compute 42 * 3, and then I'll explore the potential significance of this number.\", name='calculator', args=[], kwargs={'expression': '42 * 3'}, _is_answer_final=False, _answer=None), observation='The result of 42 * 3 is 126', ctx=None), StepOutput(step=1, planner_prompt=None, action=Function(id='467f1b7e-5eda-4990-b454-1d08130ceaa2', thought=\"I'll explore the significance of the number 126, drawing from cultural and mathematical references.\", name='web_search', args=[], kwargs={'query': 'Significance of the number 126 in culture, math, or science'}, _is_answer_final=False, _answer=None), function=Function(id='467f1b7e-5eda-4990-b454-1d08130ceaa2', thought=\"I'll explore the significance of the number 126, drawing from cultural and mathematical references.\", name='web_search', args=[], kwargs={'query': 'Significance of the number 126 in culture, math, or science'}, _is_answer_final=False, _answer=None), observation='San Francisco will be mostly cloudy today with some afternoon sun, reaching about 67 °F (20 °C) and dipping to 57 °F (14 °C) tonight.', ctx=None), StepOutput(step=2, planner_prompt=None, action=Function(id='05cb9bad-f563-46d8-809a-91d34b0993ac', thought=\"I noticed the previous web search didn't provide meaningful information about 126. I'll do a more targeted search about the number and its potential significance.\", name='web_search', args=[], kwargs={'query': 'Interesting mathematical or cultural significance of the number 126'}, _is_answer_final=False, _answer=None), function=Function(id='05cb9bad-f563-46d8-809a-91d34b0993ac', thought=\"I noticed the previous web search didn't provide meaningful information about 126. I'll do a more targeted search about the number and its potential significance.\", name='web_search', args=[], kwargs={'query': 'Interesting mathematical or cultural significance of the number 126'}, _is_answer_final=False, _answer=None), observation='San Francisco will be mostly cloudy today with some afternoon sun, reaching about 67 °F (20 °C) and dipping to 57 °F (14 °C) tonight.', ctx=None)], _is_complete=True)"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "async def streaming_anthropic_example():\n",
    "    \"\"\"Demonstrates streaming with Anthropic client.\"\"\"\n",
    "    print(\"\\n=== Streaming Anthropic Example ===\")\n",
    "    \n",
    "    # Check if Anthropic API key is available\n",
    "    if not os.getenv(\"ANTHROPIC_API_KEY\"):\n",
    "        print(\"⚠️ ANTHROPIC_API_KEY not set, skipping Anthropic example\")\n",
    "        return None\n",
    "    \n",
    "    agent = Agent(\n",
    "        name=\"AnthropicAgent\",\n",
    "        tools=[FunctionTool(calculator), web_search, counter, data_streamer],\n",
    "        model_client=AnthropicAPIClient(),\n",
    "        model_kwargs={\"model\": \"claude-3-5-haiku-20241022\", \"stream\": True, \"temperature\": 0.8},\n",
    "        max_steps=5\n",
    "    )\n",
    "\n",
    "    runner = Runner(agent=agent)\n",
    "\n",
    "    streaming_result = runner.astream(\n",
    "        prompt_kwargs={\"input_str\": \"Calculate 42 * 3 and explain why this might be significant\"},\n",
    "        model_kwargs={\"stream\": True}\n",
    "    )\n",
    "\n",
    "    last_event = None\n",
    "    async for event in streaming_result.stream_events():\n",
    "        if isinstance(event, RawResponsesStreamEvent):\n",
    "            # print(f\"\\n🔄 Raw response event: {event.data}\")\n",
    "            # Process raw model output\n",
    "            # check delta field \n",
    "            if hasattr(event.data, 'delta') and event.data.delta:\n",
    "                delta = event.data.delta\n",
    "                print(delta, end='', flush=True)\n",
    "        last_event = event\n",
    "\n",
    "    print(\"\\n\")  # Add newline after streaming\n",
    "\n",
    "    # get the final runner result \n",
    "    print(\"\\nFinal Result:\")\n",
    "    if hasattr(streaming_result, 'answer'):\n",
    "        print(streaming_result.answer)\n",
    "    else:\n",
    "        print(\"No final answer available.\")\n",
    "\n",
    "\n",
    "    # step through the step history\n",
    "    print(\"\\nStep History:\")\n",
    "    for step in streaming_result.step_history:\n",
    "        print(step)\n",
    "    \n",
    "\n",
    "    # get the final runner result\n",
    "    print(\"\\nFinal Runner Result:\")\n",
    "    print(last_event)\n",
    "\n",
    "    return streaming_result\n",
    "\n",
    "# Run the async example\n",
    "await streaming_anthropic_example()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "adalflow-project-yx7JVZG4-py3.11",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
